/*
 * File:   proxies.h
 * Author: karol
 *
 * Created on 8 listopad 2009, 19:28
 */

#ifndef _PROXIES_H
#define _PROXIES_H
namespace boostbase
{

typedef std::pair<std::string, std::string> pair_t;

/// these classes allow for such syntax:
/// int a=7;
/// double b=0.1;
/// std::string c="kura";
/// where("a",a)("b",b)("c",c) -> std::vector<std::string> { "i:7","d:0.1","string:kura" }
///

class pair_t_proxy
{
    std::vector<pair_t> values;
public:
    pair_t_proxy() {}
    pair_t_proxy(const std::vector<pair_t> & val): values(val) {}
    template<class value_type>
    pair_t_proxy operator()(const std::string & field, const value_type & val)
    {
        std::stringstream s;
        s << typeid(val).name() << ":" << val;
        values.push_back(pair_t(field, s.str()));
        return pair_t_proxy(values);
    }
    operator const std::vector<pair_t> & () const
    {
        return values;
    }
    void pop()
    {
        values.pop_back();
    }
};

///where("wielkość1","wartość1")("wielkość2","wartość2")("wielkość3","wartość3")..
template<class value_type>
pair_t_proxy where(const std::string & field, const value_type & val)
{
    std::vector<pair_t> values;
    std::stringstream s;
    s << typeid(val).name() << ":" << val;
    values.push_back(pair_t(field, s.str()));
    return pair_t_proxy(values);
}
#if defined(__GNUC__) && (__GNUC_MINOR__ < 7)
template pair_t_proxy where<double>(const std::string &, const double &);
template pair_t_proxy where<float>(const std::string &, const float &);
template pair_t_proxy where<int>(const std::string &, const int &);
template pair_t_proxy where<std::string>(const std::string &, const std::string &);
template pair_t_proxy pair_t_proxy::operator()<double>(const std::string &, const double &);
template pair_t_proxy pair_t_proxy::operator()<float>(const std::string &, const float &);
template pair_t_proxy pair_t_proxy::operator()<int>(const std::string &, const int &);
template pair_t_proxy pair_t_proxy::operator()<std::string>(const std::string &, const std::string &);
#endif
struct tween_t
{
    std::string field, begin, end;
    tween_t(const std::string & a, const std::string & b, const std::string & c):
        field(a), begin(b), end(c)
    {}
    bool operator!=(const tween_t & c) const
    {
        return (field != c.field && begin != c.begin && end != c.end);
    }
};

class tween_t_proxy
{
    std::vector<tween_t> values;
public:
    tween_t_proxy() {}
    tween_t_proxy(const std::vector<tween_t> & val): values(val) {}
    template<class value_type>
    tween_t_proxy operator()(const std::string & field, const value_type & begin, const value_type & end)
    {
        std::stringstream s1, s2;
        s1 << begin;
        s2 << end;
        values.push_back(tween_t(field, s1.str(), s2.str()));
        return tween_t_proxy(values);
    }
    operator const std::vector<tween_t> & () const
    {
        return values;
    }
    void pop()
    {
        values.pop_back();
    }
};

template<class value_type>
tween_t_proxy between(const std::string & field, const value_type & begin, const value_type & end)
{
    std::vector<tween_t> values;
    std::stringstream s1, s2;
    s1 << begin;
    s2 << end;
    values.push_back(tween_t(field, s1.str(), s2.str()));
    return tween_t_proxy(values);
}
#if defined(__GNUC__) && (__GNUC_MINOR__ < 7)
template tween_t_proxy between<double>(const std::string &, const double &, const double &);
template tween_t_proxy between<float>(const std::string &, const float &, const float &);
template tween_t_proxy between<int>(const std::string &, const int &, const int &);
template tween_t_proxy between<std::string>(const std::string &, const std::string &, const std::string &);
template tween_t_proxy tween_t_proxy::operator()<double>(const std::string &, const double &, const double &);
template tween_t_proxy tween_t_proxy::operator()<float>(const std::string &, const float &, const float &);
template tween_t_proxy tween_t_proxy::operator()<int>(const std::string &, const int &, const int &);
template tween_t_proxy tween_t_proxy::operator()<std::string>(const std::string &, const std::string &, const std::string &);
#endif
};


#endif  /* _PROXIES_H */

